package xfuzzy.alg_genetico.indeterminado.evaluation;

import xfuzzy.alg_genetico.indeterminado.model.MyXfhlProcess2;
import xfuzzy.alg_genetico.indeterminado.model.MyXfhlSpecification;
import xfuzzy.lang.Specification;
import xfuzzy.lang.XflException;
import xfuzzy.xfghl.algorithm.ResultGA;
import xfuzzy.xfghl.codification.DoubleChromosome;
import xfuzzy.xfghl.codification.Encoder;
import xfuzzy.xfghl.model.XfghlConfig;
import xfuzzy.xfghl.population.Population;
import xfuzzy.xfhl.model.XfhlData;
import xfuzzy.xfhl.model.hierStruct.XfhlHierStruct;
import xfuzzy.xfhl.model.hierStruct.XfhlModule;
import xfuzzy.xfsl.model.XfslAlgorithm;
import xfuzzy.xfsl.model.XfslAlgorithmFactory;
import xfuzzy.xfsl.model.XfslConfig;
import xfuzzy.xfsl.model.XfslEndCondition;
import xfuzzy.xfsl.model.XfslErrorFunction;
import xfuzzy.xfsl.model.XfslThread;
import xfuzzy.xfsl.model.algorithm.Marquardt;
import xfuzzy.xfsl.model.algorithm.RProp;
import xfuzzy.xfsl.model.algorithm.XfslGradientBasedAlgorithm;

public class EvaluationXfuzzy extends Evaluation {
	
	private XfghlConfig confXfhl;
	private XfhlData data;
	
	public EvaluationXfuzzy(XfghlConfig conxfghl/*, XfhlData data*/)  {
		
		this.confXfhl = conxfghl;
		//this.data = data;
	}

	@Override
	public void evaluarPoblacion(Population poblacion, ResultGA results, XfghlConfig config) {

		// Falta que de cada individuo calcule su fitness (caso definitivo)
		for (DoubleChromosome cromosoma : poblacion.getIndividuos())  {
			 evaluarIndividuo2(cromosoma, results);
		}
	}
	
	public void evaluarIndividuo2(DoubleChromosome nuevo, ResultGA result)  {
		
		// este es el que funciona
		XfhlModule modulo = Encoder.decodeBackwardAnchuraSimple(nuevo);
		XfhlHierStruct struc = new XfhlHierStruct(modulo, nuevo.getNumVariables() + nuevo.getNumModulos(), nuevo.getNumModulos());
		MyXfhlProcess2 process = new MyXfhlProcess2(confXfhl);
		process.ejecucion(struc);
		result.increaseNumEvaluations(1);
	}
	
	public void evaluarIndividuos(DoubleChromosome nuevo1, DoubleChromosome nuevo2, ResultGA results, XfghlConfig config)  {
		
		XfhlModule modulo = Encoder.decodeBackwardAnchuraSimple(nuevo1);
		XfhlHierStruct struc = new XfhlHierStruct(modulo, nuevo1.getNumVariables() + nuevo1.getNumModulos(), nuevo1.getNumModulos());
		Specification spec = null;
		try {

			spec = MyXfhlSpecification.create(struc, this.confXfhl);
		} 
		catch (XflException e) {
			e.printStackTrace();
		}
		// Ajustamos la especificacion
		this.data.setSpec(spec);
		//learning(spec);
		XfslThread lrnthread = new XfslThread(spec, createtXfslConfig());

		try {
			lrnthread.tuning();
		} 
		catch (XflException e) {
			e.printStackTrace();
		}
		System.out.println(this.data.getFinalError());
		nuevo1.setFitness(this.data.getFinalError());
	}
	
	private XfslConfig createtXfslConfig() {
		
		XfslConfig xfslConfig = new XfslConfig();

		// Parametros del algoritmo
		double param[] = { this.confXfhl.getIniUpd(), this.confXfhl.getIncFact(), this.confXfhl.getDecFact() };

		int alg = -1;
		int err = XfslErrorFunction.MEAN_SQUARE_ERROR;
		int end = XfslEndCondition.EPOCH;

		if (this.confXfhl.getAlgorithm() == 0) {
			alg = XfslAlgorithm.RPROP;

			RProp rprop;
			try {
				rprop = (RProp) XfslAlgorithmFactory.createAlgorithm(alg, param);
				// rprop.setOption(RProp.COMPUTE,
				// this.confXfhl.getPerturbation());
				rprop.setOption(RProp.COMPUTE,
						XfslGradientBasedAlgorithm.COMPUTE);
				xfslConfig = new XfslConfig();
				xfslConfig.trainingfile = this.confXfhl.getDataSetFile();
				xfslConfig.algorithm = rprop;
				xfslConfig.errorfunction = new XfslErrorFunction(err);
				xfslConfig.endcondition.setLimit(end, this.confXfhl.getnumIterAjust());

			} 
			catch (XflException e) {
				e.printStackTrace();
			}
		} else if (this.confXfhl.getAlgorithm() == 1) {

			alg = XfslAlgorithm.MARQUARDT;
			Marquardt marq;
			try {
				marq = (Marquardt) XfslAlgorithmFactory.createAlgorithm(alg, param);
				// marq.setOption(Marquardt.COMPUTE,
				// this.confXfhl.getPerturbation());
				marq.setOption(Marquardt.COMPUTE, 0);
				xfslConfig = new XfslConfig();
				xfslConfig.trainingfile = this.confXfhl.getDataSetFile();
				xfslConfig.algorithm = marq;
				xfslConfig.errorfunction = new XfslErrorFunction(err);
				xfslConfig.endcondition.setLimit(end, this.confXfhl.getnumIterAjust());

			} 
			catch (XflException e) {
				e.printStackTrace();
			}
		}
		return xfslConfig;
	}
}
